package com.hfy.user.ws;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hfy.model.dto.user.OpenSessionDto;
import com.hfy.model.po.user.MessagePo;
import com.hfy.model.po.user.SessionPo;
import com.hfy.model.ws.privateMessage.CommonMessage;
import com.hfy.model.ws.privateMessage.OriginalMessage;
import com.hfy.user.service.MessageService;
import com.hfy.user.service.SessionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @ author 韩
 * time: 2024/10/7 1:29
 */

@ServerEndpoint("/ws/message/{account}")
@Slf4j
@Component
public class WsPrivateMessage {


    //声明session对象，通过该对象可以发送消息给指定的用户
    private Session session;
    // 存储session信息
    private static final Map<String, Session> onlineUsers = new ConcurrentHashMap<>();


    private static ApplicationContext applicationContext;

    // 不使用静态类来存储聊天室里的用户，用redis实现
    public static void setApplicationContext(ApplicationContext applicationContext) {
        WsPrivateMessage.applicationContext = applicationContext;
    }

    private static StringRedisTemplate redisTemplate;

    private static MessageService messageService;
    private static SessionService sessionService;

    private static RabbitTemplate rabbitTemplate;

    private String account;







    @OnOpen
    public void onOpen(Session session, @PathParam("account") String account, EndpointConfig config)  {
        // 配置依赖
        redisTemplate = applicationContext.getBean(StringRedisTemplate.class);
        messageService = applicationContext.getBean(MessageService.class);
        sessionService = applicationContext.getBean(SessionService.class);
        rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);

        // 获取携带的account和roomId
        this.account = account;
        this.session = session;

        onlineUsers.put(account, this.session);



        log.info("OK");
    }




    @OnMessage
    public void onMessage(String message, @PathParam("account") String account) throws IOException {
        // 收到自己的客户端发过来的消息了
        // 所以结构类似
        /**   {
          type：... ，
          data：{
              fromAccount: ... ，
              toAccount: ... ，
              message: ...
            }
         }    */
        // 除了data里的结构不同，外面的结构都是一样的
        OriginalMessage originalMessage = JSON.parseObject(message, OriginalMessage.class);
        Class<?> suitClass = originalMessage.getSuitClass();
        Object o = JSON.parseObject(originalMessage.getData(), suitClass);
        String toAccount = originalMessage.getToAccount();
        if (originalMessage.getType() == 0) {

            CommonMessage data = (CommonMessage) o;
            // 最简单的逻辑

            if (onlineUsers.get(toAccount) != null) onlineUsers.get(toAccount).getBasicRemote().sendText(message);
            if (onlineUsers.get(account) != null) onlineUsers.get(account).getBasicRemote().sendText(message);


        } else if (originalMessage.getType() == 1) {
//            simpleMessage = "[图片消息]";

        } else if (originalMessage.getType() == 2) {
//            simpleMessage = "[卡片消息]";
        }
        LocalDateTime now = LocalDateTime.now();;

        // 发过去成功后，把消息存储到消息表里
        MessagePo messagePo1 = new MessagePo();
        messagePo1.setType(originalMessage.getType());
        messagePo1.setSessionId(originalMessage.getSessionId());
        messagePo1.setData(originalMessage.getData());
        messagePo1.setSendTime(now);
        messagePo1.setAccount(account);
        messagePo1.setToAccount(toAccount);
        messageService.save(messagePo1);


        sessionService.open(new OpenSessionDto(toAccount, account));

        // 另一端也要存储
        LambdaQueryWrapper<SessionPo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SessionPo::getAccount, toAccount).eq(SessionPo::getToAccount, account);
        SessionPo one = sessionService.getOne(queryWrapper);
        MessagePo messagePo2 = new MessagePo();
        messagePo2.setType(originalMessage.getType());
        messagePo2.setData(originalMessage.getData());
        messagePo2.setSessionId(one.getId());
        messagePo2.setSendTime(now);
        messagePo2.setAccount(account);
        messagePo2.setToAccount(toAccount);
        messageService.save(messagePo2);






    }


    @OnClose
    public void onClose() {

        onlineUsers.remove(account);

    }

    @OnError
    public void onError(Session session, Throwable error) {

        log.error(error.toString());

        error.printStackTrace();
    }

}
